
package sg.edu.nus.iss.billing.controller;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import sg.edu.nus.iss.billing.exceptions.ControllerException;
import sg.edu.nus.iss.billing.model.bill.BillingPeriod;
import sg.edu.nus.iss.billing.model.transaction.PaymentTransaction;
import sg.edu.nus.iss.billing.model.transaction.ServiceTransaction;
import sg.edu.nus.iss.billing.model.transaction.ServiceTransactionType;

/**
 * @author ZiFeng, Thurien, YiNi
 *
 */
public class TransactionController {

	private static String dataLocation = "data/inbound/transactions_";
	
	private static Map<String, Map<String, List<ServiceTransaction>>> transactionDataMap = new HashMap<String, Map<String, List<ServiceTransaction>>>();

	public TransactionController() {
	}
	
	private List<ServiceTransaction> readServiceTransaction(String fileName) throws Exception
	{
		List<ServiceTransaction> list = new ArrayList<ServiceTransaction>();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			
			String line = null;
			while ((line = bufferedReader.readLine()) != null) {
				String[] strs = line.split(",");
				if(strs != null && strs.length == 5)
				{
						ServiceTransaction obj = new ServiceTransaction();
						obj.setAccountNo(strs[0]);
						obj.setServiceType(getServiceTransactionType(strs[1]));
						obj.setNumberCalled(strs[2]);
						obj.setCallTs(strs[3]);
						obj.setDurationOfCall(Double.parseDouble(strs[4]));
						list.add(obj);
				}
					
			}
			bufferedReader.close();
		return list;
		
	}
	
	private List<PaymentTransaction> readPaymentTransaction(String fileName) throws Exception
	{
		List<PaymentTransaction> list = new ArrayList<PaymentTransaction>();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
			
			String line = null;
			while ((line = bufferedReader.readLine()) != null) {
				String[] strs = line.split(",");
				if(strs != null && strs.length == 3)
				{
					PaymentTransaction obj = new PaymentTransaction();
					obj.setAccountNo(strs[0]);
					obj.setPaymentAmt(Double.parseDouble(strs[2]));
					obj.setPaymentDate(strs[1]);
					list.add(obj);
				}
			}
			bufferedReader.close();
		return list;
	}
	
	public List<ServiceTransaction> getServiceTransaction(String accountNo, String fileName)
	{
		return getServiceTransaction(fileName).get(accountNo);
	}
	
	public List<ServiceTransaction> getServiceTransaction(String accountNo, BillingPeriod billingPeriod) throws ControllerException
	{
		String month = String.format("%02d", billingPeriod.getBillingMonth().getNumber());
		int year = billingPeriod.getBillingYear();
		String locationIndex = dataLocation+year+month+".txt";
		Map<String, List<ServiceTransaction>> map = transactionDataMap.get(locationIndex);
		if( map != null)
		{
			return map.get(accountNo);
		}else
		{
			Map<String, List<ServiceTransaction>> transMap = getServiceTransaction(locationIndex);
			if(transMap == null || transMap.isEmpty())
			{
				throw new ControllerException("Data Source is No Found! please check @" + locationIndex);
			}else
			{
				transactionDataMap.put(locationIndex, transMap);
				return transactionDataMap.get(locationIndex).get(accountNo);
			}
		}
	}
	
	public Map<String, List<ServiceTransaction>> getServiceTransaction(String fileName)
	{
		Map<String, List<ServiceTransaction>> map = new HashMap<String, List<ServiceTransaction>>();
		List<ServiceTransaction> allTransaction = null;
		try {
			allTransaction = readServiceTransaction(fileName);
			for(ServiceTransaction tran: allTransaction)
			{
				if(map.get(tran.getAccountNo()) == null)
				{
					List<ServiceTransaction> list = new ArrayList<ServiceTransaction>();	
					map.put(tran.getAccountNo(), list);	
				}
				map.get(tran.getAccountNo()).add(tran);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
	
	public Map<String, PaymentTransaction> getPaymentTransaction(String fileName)
	{
		Map<String, PaymentTransaction> map = new HashMap<String, PaymentTransaction>();
		List<PaymentTransaction> allTransaction = null;
		try {
			allTransaction = readPaymentTransaction(fileName);
			for(PaymentTransaction tran: allTransaction)
			{
				map.put(tran.getAccountNo(), tran);	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
	
	private ServiceTransactionType getServiceTransactionType(String type)
	{
		ServiceTransactionType serviceTransactionType = null;
		if("dLocal".equalsIgnoreCase(type))	{
			serviceTransactionType = ServiceTransactionType.dLocal;
		}else if("dIDD".equalsIgnoreCase(type))	{
			serviceTransactionType = ServiceTransactionType.dIDD;
		}else if("mLocal".equalsIgnoreCase(type))	{
			serviceTransactionType = ServiceTransactionType.mLocal;
		}else if("mIDD".equalsIgnoreCase(type))	{
			serviceTransactionType = ServiceTransactionType.mIDD;
		}else if("mRoaming".equalsIgnoreCase(type))	{
			serviceTransactionType = ServiceTransactionType.mRoaming;
		}
		return serviceTransactionType;
	}

}
